/* 
 * Quechua - the lightweight data mining framework
 *
 * Copyright (C) 2012 Marek Denis <quechua@octogan.net>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "../include/quechua.h"

void Quechua::init() {
    try {
        logs = new Logging();
        loop = new ev::default_loop(0);
        signals = new signals_s;
        threads = new Threads();
        config = new Config();                                                                
        modules = new Modules("/opt/quechua/lib/quechua/"); // make it more portable
        components = new components_s;
    } catch(alloc_ex& ex) {
        LOG(CRITIC) << "Cannot allocate memory for one of Quechua components."
                    << " Exiting";
        exit(EXIT_FAILURE);
    }
};

Quechua::~Quechua() {
    loop->unloop();
    LOG(INFO) << "Destroying Quechua";
    delete threads;
    delete config;
    delete components;
    delete modules;
    delete signals;
    delete loop;                                                                          
    logs->close_output();
    delete logs;
};

void Quechua::prepare_channels() {
    channels_map::iterator it = components->channels.begin();
    channels_map::iterator end= components->channels.end();
    for(it;it!=end;++it) {
        if(!it->second->prepare())
            LOG(WARN) << "Channel " << it->second->internal->name
                      << " was not prepared";
    }
};

void Quechua::prepare_loggers() {
    loggers_map::iterator it = components->loggers.begin();
    loggers_map::iterator end= components->loggers.end();
    for(it;it!=end;++it) {
        if(!it->second->prepare())
            LOG(WARN) << "Logger " << it->second->internal->name
                      << " was not prepared";
    }
};

void Quechua::prepare_workflows() {
    workflows_map::iterator it = components->workflows.begin();
    workflows_map::iterator end= components->workflows.end();
    
    for(it;it!=end;++it) it->second->prepare();
    
};

void Quechua::start_channels() {
    channels_map::iterator it = components->channels.begin();
    channels_map::iterator end= components->channels.end();
    for(it;it!=end;++it)
        if(!it->second->start()) {
            LOG(WARN) << "Channel " << it->second->internal->name
                      << " was not started";
        }
    
};

void Quechua::start_loggers() {
    loggers_map::iterator it = components->loggers.begin();
    loggers_map::iterator end= components->loggers.end();
    for(it;it!=end;++it) {
        if(!it->second->start()) {
            LOG(WARN) << "Logger " << it->second->internal->name
                      << " was not started";
        }
    }

};

void Quechua::start_workflows() {
    workflows_map::iterator it = components->workflows.begin();
    workflows_map::iterator end= components->workflows.end();
    for(it;it!=end;++it) it->second->start();
};

void Quechua::stop_channels() {
    channels_map::iterator it,end;
    it = components->channels.begin();
    end= components->channels.end();
    for(;it!=end;++it) it->second->stop();
};

void Quechua::stop_workflows() {
    workflows_map::iterator it,end;
    it = components->workflows.begin();
    end= components->workflows.end();
    for(;it!=end;++it) it->second->stop();
};

void Quechua::stop_loggers() {
    loggers_map::iterator it,end;
    it = components->loggers.begin();
    end= components->loggers.end();
    for(;it!=end;++it) it->second->stop();
};

void Quechua::destroy_channels() {
    channels_map::iterator it,end;
    it = components->channels.begin();
    end= components->channels.end();

    for(;it!=end;++it) delete it->second;
    components->channels.clear();
};

void Quechua::destroy_workflows() {
    workflows_map::iterator it,end;
    it = components->workflows.begin();
    end= components->workflows.end();
    for(;it!=end;++it) delete it->second;
    components->workflows.clear();
};

void Quechua::destroy_loggers() {
    loggers_map::iterator it,end;
    it = components->loggers.begin();
    end= components->loggers.end();
    for(;it!=end;++it) delete it->second;
    components->loggers.clear();
};

void Quechua::prepare_signals() {
    signals->sigint.set<sigint_cb>();
    signals->sigint.set(SIGINT);
    signals->sigint.set(*g_quechua->loop);
    signals->sigint.start();
};

void Quechua::stop_signals() {
    signals->sigint.stop();
};

void sigint_cb(ev::sig& watcher,int revents) {
    LOG(MESSAGE) << "Just caught INTERRUPT signal, time to say goodbye";
    g_quechua->loop->unloop();  
};

/**
 * Function daemonizing Quechua
 * - redirects output from stdout to file
 * - detaches from the terminal
 **/ 
void Quechua::daemonize() {
    if(!logs) {
        LOG(CRITIC) << "Logging module is not initialized, exiting whole application!";
        exit(-1);
    }
    logs->redirect_output("/opt/quechua/log/quechua.log");
    daemon(1,0);
};
